/**
 * API请求管理器
 * 实现请求去重、防抖、重试机制
 */

interface RequestConfig {
  url: string;
  params?: any;
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
  timeout?: number;
  retries?: number;
  retryDelay?: number;
}

interface PendingRequest {
  promise: Promise<any>;
  timestamp: number;
}

class RequestManager {
  private pendingRequests = new Map<string, PendingRequest>();
  private debounceTimers = new Map<string, number>();
  private readonly DEFAULT_DEBOUNCE_DELAY = 300; // 300ms防抖
  private readonly DEFAULT_RETRY_COUNT = 3;
  private readonly DEFAULT_RETRY_DELAY = 1000; // 1秒

  /**
   * 生成请求的唯一键
   */
  private generateRequestKey(config: RequestConfig): string {
    const { url, params, method = 'GET' } = config;
    const paramStr = params ? JSON.stringify(params) : '';
    return `${method}:${url}:${paramStr}`;
  }

  /**
   * 执行请求（带去重）
   */
  async request<T>(
    requestFn: () => Promise<T>,
    config: RequestConfig,
    options: {
      enableDeduplication?: boolean;
      enableDebounce?: boolean;
      debounceDelay?: number;
    } = {}
  ): Promise<T> {
    const {
      enableDeduplication = true,
      enableDebounce = false,
      debounceDelay = this.DEFAULT_DEBOUNCE_DELAY
    } = options;

    const requestKey = this.generateRequestKey(config);

    // 防抖处理
    if (enableDebounce) {
      return this.debounceRequest(requestFn, requestKey, debounceDelay);
    }

    // 请求去重
    if (enableDeduplication) {
      const pending = this.pendingRequests.get(requestKey);
      if (pending) {
        console.log(`Request deduplication: ${requestKey}`);
        return pending.promise;
      }
    }

    // 执行请求
    const promise = this.executeWithRetry(requestFn, config);
    
    if (enableDeduplication) {
      this.pendingRequests.set(requestKey, {
        promise,
        timestamp: Date.now()
      });

      // 请求完成后清理
      promise.finally(() => {
        this.pendingRequests.delete(requestKey);
      });
    }

    return promise;
  }

  /**
   * 防抖请求
   */
  private debounceRequest<T>(
    requestFn: () => Promise<T>,
    key: string,
    delay: number
  ): Promise<T> {
    return new Promise((resolve, reject) => {
      // 清除之前的定时器
      const existingTimer = this.debounceTimers.get(key);
      if (existingTimer) {
        clearTimeout(existingTimer);
      }

      // 设置新的定时器
      const timer = setTimeout(async () => {
        try {
          const result = await requestFn();
          resolve(result);
        } catch (error) {
          reject(error);
        } finally {
          this.debounceTimers.delete(key);
        }
      }, delay);

      this.debounceTimers.set(key, timer);
    });
  }

  /**
   * 带重试的请求执行
   */
  private async executeWithRetry<T>(
    requestFn: () => Promise<T>,
    config: RequestConfig
  ): Promise<T> {
    const maxRetries = config.retries || this.DEFAULT_RETRY_COUNT;
    const retryDelay = config.retryDelay || this.DEFAULT_RETRY_DELAY;

    let lastError: any;

    for (let attempt = 0; attempt <= maxRetries; attempt++) {
      try {
        return await requestFn();
      } catch (error) {
        lastError = error;
        
        // 如果是最后一次尝试，直接抛出错误
        if (attempt === maxRetries) {
          break;
        }

        // 检查是否应该重试
        if (!this.shouldRetry(error)) {
          break;
        }

        console.warn(`Request failed, retrying (${attempt + 1}/${maxRetries}):`, {
          url: config.url,
          method: config.method,
          error: (error as any)?.message || String(error),
          status: (error as any)?.response?.status,
          code: (error as any)?.code
        });
        
        // 等待后重试
        await this.delay(retryDelay * Math.pow(2, attempt)); // 指数退避
      }
    }

    throw lastError;
  }

  /**
   * 判断是否应该重试
   */
  private shouldRetry(error: any): boolean {
    // 网络错误
    if (error.code === 'NETWORK_ERROR' || error.code === 'ERR_NETWORK') return true;

    // 超时错误
    if (error.code === 'ECONNABORTED' || error.code === 'TIMEOUT') return true;

    // 5xx服务器错误才重试
    if (error.response?.status >= 500) return true;

    // 特定的网络相关错误
    if (error.message?.includes('Network Error')) return true;
    if (error.message?.includes('timeout')) return true;

    // 429 Too Many Requests - 可以重试
    if (error.response?.status === 429) return true;

    // 4xx客户端错误不重试（除了429）
    if (error.response?.status >= 400 && error.response?.status < 500) return false;

    return false;
  }

  /**
   * 延迟函数
   */
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 批量请求
   */
  async batchRequest<T>(
    requests: Array<{
      requestFn: () => Promise<T>;
      config: RequestConfig;
    }>,
    options: {
      concurrency?: number;
      failFast?: boolean;
    } = {}
  ): Promise<T[]> {
    const { concurrency = 5, failFast = false } = options;

    if (concurrency >= requests.length) {
      // 如果并发数大于等于请求数，直接并行执行
      if (failFast) {
        return Promise.all(requests.map(req =>
          this.executeWithRetry(req.requestFn, req.config)
        ));
      } else {
        const results = await Promise.allSettled(requests.map(req =>
          this.executeWithRetry(req.requestFn, req.config)
        ));
        return results
          .filter((result): result is PromiseFulfilledResult<Awaited<T>> => result.status === 'fulfilled')
          .map(result => result.value);
      }
    }

    // 分批执行
    const results: T[] = [];
    for (let i = 0; i < requests.length; i += concurrency) {
      const batch = requests.slice(i, i + concurrency);
      const batchPromises = batch.map(req =>
        this.executeWithRetry(req.requestFn, req.config)
      );

      if (failFast) {
        const batchResults = await Promise.all(batchPromises);
        results.push(...batchResults);
      } else {
        const batchResults = await Promise.allSettled(batchPromises);
        const successResults = batchResults
          .filter((result): result is PromiseFulfilledResult<Awaited<T>> => result.status === 'fulfilled')
          .map(result => result.value);
        results.push(...successResults);
      }
    }

    return results;
  }

  /**
   * 清理过期的待处理请求
   */
  cleanup(): void {
    const now = Date.now();
    const EXPIRY_TIME = 30 * 1000; // 30秒

    for (const [key, request] of this.pendingRequests.entries()) {
      if (now - request.timestamp > EXPIRY_TIME) {
        this.pendingRequests.delete(key);
      }
    }
  }

  /**
   * 获取统计信息
   */
  getStats() {
    return {
      pendingRequests: this.pendingRequests.size,
      debounceTimers: this.debounceTimers.size
    };
  }

  /**
   * 取消所有待处理的请求
   */
  cancelAll(): void {
    this.pendingRequests.clear();
    
    // 清理防抖定时器
    for (const timer of this.debounceTimers.values()) {
      clearTimeout(timer);
    }
    this.debounceTimers.clear();
  }
}

// 创建全局请求管理器实例
export const requestManager = new RequestManager();

// 定期清理
setInterval(() => {
  requestManager.cleanup();
}, 30 * 1000); // 每30秒清理一次

// 在开发环境下暴露到全局对象，方便调试
if (import.meta.env.DEV) {
  (window as any).requestManager = requestManager;
}

export default RequestManager;
